package com.graphics.ui;

import java.io.IOException;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.bin.activities.R;
import com.bin.comunication.webcam.MjpegInputStream;

public class MjpegView extends SurfaceView implements SurfaceHolder.Callback {
	public final static int POSITION_UPPER_LEFT  = 9;
	public final static int POSITION_UPPER_RIGHT = 3;
	public final static int POSITION_LOWER_LEFT  = 12;
	public final static int POSITION_LOWER_RIGHT = 6;

	public final static int SIZE_STANDARD   = 1; 
	public final static int SIZE_BEST_FIT   = 4;
	public final static int SIZE_FULLSCREEN = 8;

	private MjpegViewThread thread;
	private MjpegInputStream mIn = null;    
	private boolean showFps = false;
	private boolean mRun = false;
	private boolean surfaceDone = false;    
	private Paint overlayPaint;
	private int overlayTextColor;
	private int overlayBackgroundColor;
	private int ovlPos;
	private int dispWidth;
	private int dispHeight;
	private int displayMode;
    private String URLs="";
    
	private void init(Context context) {
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        thread = new MjpegViewThread(holder, context);
        setFocusable(true);
        overlayPaint = new Paint();
        overlayPaint.setTextAlign(Paint.Align.LEFT);
        overlayPaint.setTextSize(12);
        overlayPaint.setTypeface(Typeface.DEFAULT);
        overlayTextColor = Color.WHITE;
        overlayBackgroundColor = Color.BLACK;
        ovlPos = MjpegView.POSITION_LOWER_RIGHT;
        displayMode = MjpegView.SIZE_STANDARD;
        dispWidth = getWidth();
        dispHeight = getHeight();
        URLs=context.getString(R.string.WebCam_Address);    
    }
    
    public MjpegView(Context context, AttributeSet attrs) { 
    	super(context, attrs); 
    	init(context); 
    	}
    

    public void startPlayback() { 
        if(mIn != null) {
            mRun = true;
            thread.start();    		
        }
    }
    
    public void stopPlayback() { 
        mRun = false;
        boolean retry = true;
        while(retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {}
        }
    }
    
    public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { 
    	thread.setSurfaceSize(w, h);   
    }

    public void surfaceDestroyed(SurfaceHolder holder) { 
    	surfaceDone = false; 
        stopPlayback();
    }
    
    public MjpegView(Context context) { 
    	super(context); 
    	init(context); 
        	
    }

    public MjpegView(Context context, AttributeSet attrs,int defaultStyle){
    	super(context,attrs,defaultStyle); 	init(context);
    }

    public void surfaceCreated(SurfaceHolder holder) { 
    	surfaceDone = true;
    	Thread th=new MjpegServiceLauncher();
    	th.start();
    }
    
    public void showFps(boolean b) { showFps = b; }
    
    public void setSource(MjpegInputStream source) { 
    	mIn = source; 
    	startPlayback();
    }
    public void setOverlayPaint(Paint p) { overlayPaint = p; }
    public void setOverlayTextColor(int c) { overlayTextColor = c; }
    public void setOverlayBackgroundColor(int c) { overlayBackgroundColor = c; }
    public void setOverlayPosition(int p) { ovlPos = p; }
    public void setDisplayMode(int s) { displayMode = s; }
    public boolean getSurface(){return surfaceDone;}

//------------------------------------------------------------------------------------------------------------------
	private class MjpegServiceLauncher extends Thread{
		
		@Override
		public void run(){
		    boolean surface;
			
				
			URLs="http://"+URLs+"/video.cgi?resolution=320x240";
			surface=getSurface();
	        MjpegInputStream mjs=MjpegInputStream.read(URLs); 		
			System.out.println("status:"+surface);
			setSource(mjs);
		    setDisplayMode(MjpegView.SIZE_BEST_FIT);
			showFps(true);
		}
	}
    
//------------------------------------------------------------------------------------------------------------------

	private class MjpegViewThread extends Thread {
	    private SurfaceHolder mSurfaceHolder;
	    private int frameCounter = 0;
	    private long start;
	    private Bitmap ovl;
	    private Matrix mRotationMatrix;
	    private int rotationDegree=90;
	    
	    public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { 
	    	mSurfaceHolder = surfaceHolder; 
	    	mRotationMatrix = new Matrix();
	    }
	
	    private Rect destRect(int bmw, int bmh) {
	        int tempx;
	        int tempy;
	        if (displayMode == MjpegView.SIZE_STANDARD) {
	            tempx = (dispWidth / 2) - (bmw / 2);
	            tempy = (dispHeight / 2) - (bmh / 2);
	            return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
	        }
	        if (displayMode == MjpegView.SIZE_BEST_FIT) {
	            float bmasp = (float) bmw / (float) bmh;
	            bmw = dispWidth;
	            bmh = (int) (dispWidth / bmasp);
	            if (bmh > dispHeight) {
	                bmh = dispHeight;
	                bmw = (int) (dispHeight * bmasp);
	            }
	            tempx = (dispWidth / 2) - (bmw / 2);
	            tempy = (dispHeight / 2) - (bmh / 2);
	            return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
	        }
	        if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight);
	        return null;
	    }
	     
	    public void setSurfaceSize(int width, int height) {
	        synchronized(mSurfaceHolder) {
	            dispWidth = width;
	            dispHeight = height;
	        }
	    }
	     
	    private Bitmap makeFpsOverlay(Paint p, String text) {
	        Rect b = new Rect();
	        p.getTextBounds(text, 0, text.length(), b);
	        int bwidth  = b.width()+2;
	        int bheight = b.height()+2;
	        Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
	        Canvas c = new Canvas(bm);
	        p.setColor(overlayBackgroundColor);
	        c.drawRect(0, 0, bwidth, bheight, p);
	        p.setColor(overlayTextColor);
	        c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p);
	        return bm;        	 
	    }
	
	    public void run() {
	        start = System.currentTimeMillis();
	        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
	        Bitmap bm;
	        int width;
	        int height;
	        Rect destRect;
	        Canvas c = null;
	        Paint p = new Paint();
	        String fps = "";
	        while (mRun) {
	            if(surfaceDone) {
	                try {
	                    c = mSurfaceHolder.lockCanvas();
	                    synchronized (mSurfaceHolder) {
	                        try {
	                            bm = mIn.readMjpegFrame();
	                            destRect = destRect(bm.getWidth(),bm.getHeight());
	                            c.drawColor(Color.BLACK);
	                   //         mRotationMatrix.postRotate(rotationDegree,bm.getWidth()/2,bm.getHeight()/2);
	                   // 		Bitmap rotatedBm = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), mRotationMatrix, true);
	                 
	                            c.drawBitmap(bm, null, destRect, p);
	                            if(showFps) {
	                                p.setXfermode(mode);
	                                if(ovl != null) {
	                                	height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom-ovl.getHeight();
	                                	width  = ((ovlPos & 8) == 8) ? destRect.left : destRect.right -ovl.getWidth();
	                                	mRotationMatrix.postRotate(rotationDegree,ovl.getWidth()/2,ovl.getHeight()/2);
	                                	c.drawBitmap(ovl, width, height, null);
	                                }
	                                p.setXfermode(null);
	                                frameCounter++;
	                                if((System.currentTimeMillis() - start) >= 1000) {
	                                    fps = String.valueOf(frameCounter)+"fps";
	                                    frameCounter = 0; 
	                                    start = System.currentTimeMillis();
	                                    ovl = makeFpsOverlay(overlayPaint, fps);
	                                }
	                            }
	                        } catch (IOException e) {}
	                          catch (NullPointerException e){
	                        	  
	                          }
	                    }
	                } finally { if (c != null) mSurfaceHolder.unlockCanvasAndPost(c); }
	            }
	        }
	    }
	}
}